package ch.ethz.fcl.metrobuzz.algorithm.database;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ch.ethz.fcl.metrobuzz.data.long_term_trajectory.TrajectoryGraph;
import ch.ethz.fcl.metrobuzz.data.long_term_trajectory.node.LTTNode;
import ch.ethz.fcl.metrobuzz.data.long_term_trajectory.trajectory.Trajectory;
import ch.ethz.fcl.metrobuzz.render.interchange.ltt.LongTermTrajectoryRender;
import ch.ethz.fcl.metrobuzz.render.techniques.stacked_graph.StackedGraphLink;
import ch.ethz.fcl.metrobuzz.render.techniques.stacked_graph.StackedGraphNode;

public class LongTermTransaction {
	private TrajectoryGraph trans;
	private LTTNode selectedNode;

	private List<Trajectory> allTransList;
	private List<LTTNode> freqAssocNodeList;
	private List<Integer> freqItemList;
	private AssociationNodeTransactionList freqTransList;
	private List<Integer> freqTransIndices;

	private List<Integer> visitedTrans;

	private List<StackedGraphNode> stackGraphNodes;
	private List<StackedGraphLink> stackGraphLinks;

	private Map<Integer, Integer> indexToSGNIndexMap;

	private boolean debug = true;

	public LongTermTransaction(TrajectoryGraph trans,
			LTTNode selectedNode,
			AssociationNodeTransactionList transList,
			List<Integer> freqTransIndices) {
		this.trans = trans;
		this.selectedNode = selectedNode;
		allTransList = this.trans.getSelectedTranList();
		freqTransList = transList;
		this.freqTransIndices = freqTransIndices;

		System.out.println("\nFor input long term trans "
				+ transList.toString());
		updateFreqAssocNode();
		calHistgram();
	}

	private void updateFreqAssocNode() {
		this.freqAssocNodeList = new ArrayList<LTTNode>();
		int selectedNodeIndex = freqTransList.getNodeList().indexOf(
				selectedNode);
		if (selectedNodeIndex == -1)
			return;

		for (int i = 0; i < freqTransList.size(); i++) {
			LTTNode node = freqTransList.getNodeList().get(i);
			if (!freqAssocNodeList.contains(node))
				freqAssocNodeList.add(node);
		}

		if (debug) {
			System.out.println("There are " + freqAssocNodeList.size()
					+ " frequent association nodes, they are");
			for (LTTNode node : freqAssocNodeList)
				System.out.print(node.toNode().getId() + " ");
			System.out.println("Transaction size " + freqTransIndices.size());
		}

		freqItemList = new ArrayList<Integer>();
		stackGraphNodes = new ArrayList<StackedGraphNode>();
		stackGraphLinks = new ArrayList<StackedGraphLink>();
		indexToSGNIndexMap = new HashMap<Integer, Integer>();

		for (LTTNode assoNode : freqAssocNodeList) {
			freqItemList.add(assoNode.getId());

			StackedGraphNode sgn = new StackedGraphNode(assoNode.toNode()
					.toPoint());
			indexToSGNIndexMap.put(assoNode.getId(), stackGraphNodes.size());
			stackGraphNodes.add(sgn);

			stackGraphLinks.add(new StackedGraphLink(indexToSGNIndexMap
					.get(assoNode.getId())));
		}
	}

	private void calHistgram() {
		visitedTrans = new ArrayList<Integer>();
		for (Integer transIndex : freqTransIndices)
			if (!visitedTrans.contains(transIndex)) {
				Trajectory trans = allTransList.get(transIndex);
				List<Integer> itemList = trans.getItemList();
				int startItem = -1;
				for (Integer item : itemList)
					if (freqItemList.contains(item)) {
						startItem = item;
						break;
					}

				if (startItem != -1) {
					int startItemIndex = indexToSGNIndexMap.get(startItem);
					for (Integer item : itemList)
						if (freqItemList.contains(item)) {
							int sgnIndex = indexToSGNIndexMap.get(item);
							// if (sgnIndex != startItemIndex)
							stackGraphNodes.get(sgnIndex).addItem(
									startItemIndex, 1);
						}
				}
				visitedTrans.add(transIndex);
			}

		for (StackedGraphNode node : stackGraphNodes)
			if (node.getPos().equals(selectedNode.toNode().toPoint()))
				System.out.println(node.toString());
	}

	public List<StackedGraphLink> getLinks() {
		return stackGraphLinks;
	}

	public List<StackedGraphNode> getNodes() {
		return stackGraphNodes;
	}

	public void render() {
		// if (stackGraphLinks != null)
		// for (int i = 0; i < stackGraphLinks.size(); i++) {
		// // if (i != 5)
		// // continue;
		// StackedGraphLink sgl = stackGraphLinks.get(i);
		// sgl.render(0.000005f, stackGraphNodes);
		// }

		LongTermTrajectoryRender.render(trans.getData(), selectedNode, this);
	}
}
